
/* Copyright (c) Mark J. Kilgard, 1994. */

/**
 * (c) Copyright 1993, 1994, Silicon Graphics, Inc.
 * ALL RIGHTS RESERVED
 * Permission to use, copy, modify, and distribute this software for
 * any purpose and without fee is hereby granted, provided that the above
 * copyright notice appear in all copies and that both the copyright notice
 * and this permission notice appear in supporting documentation, and that
 * the name of Silicon Graphics, Inc. not be used in advertising
 * or publicity pertaining to distribution of the software without specific,
 * written prior permission.
 *
 * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS"
 * AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE,
 * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR
 * FITNESS FOR A PARTICULAR PURPOSE.  IN NO EVENT SHALL SILICON
 * GRAPHICS, INC.  BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT,
 * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY
 * KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION,
 * LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF
 * THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC.  HAS BEEN
 * ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE
 * POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 * US Government Users Restricted Rights
 * Use, duplication, or disclosure by the Government is subject to
 * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph
 * (c)(1)(ii) of the Rights in Technical Data and Computer Software
 * clause at DFARS 252.227-7013 and/or in similar or successor
 * clauses in the FAR or the DOD or NASA FAR Supplement.
 * Unpublished-- rights reserved under the copyright laws of the
 * United States.  Contractor/manufacturer is Silicon Graphics,
 * Inc., 2011 N.  Shoreline Blvd., Mountain View, CA 94039-7311.
 *
 * OpenGL(TM) is a trademark of Silicon Graphics, Inc.
 */
/*----------------------------------------------------------------------------
 *
 * ohidden.c : openGL (GLUT) example showing how to use stencils
 *             to draw outlined polygons.
 *
 * Author : Yusuf Attarwala
 *          SGI - Applications
 * Date   : Jul 93
 *
 * Update : Mark Kilgard
 * Date   : Feb 95
 *
 *    note : the main intent of this program is to demo the stencil
 *           plane functionality, hence the rendering is kept
 *           simple (wireframe).
 *
 *---------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <GL/glut.h>

static int stencilOn = 1;

/* function declarations */

void
drawScene(void), setMatrix(void), animation(void), resize(int w, int h),
          keyboard(unsigned char c, int x, int y), menu(int choice), drawWireframe(int face),
          drawFilled(int face);

/* global variables */

float ax, ay, az;       /* angles for animation */

/* coords of a cube */
static GLfloat cube[8][3] = {
	0.0, 0.0, 0.0,
	1.0, 0.0, 0.0,
	1.0, 0.0, 1.0,
	0.0, 0.0, 1.0,
	1.0, 1.0, 0.0,
	1.0, 1.0, 1.0,
	0.0, 1.0, 1.0,
	0.0, 1.0, 0.0
};

static int faceIndex[6][4] = {
	0, 1, 2, 3,
	1, 4, 5, 2,
	4, 7, 6, 5,
	7, 0, 3, 6,
	3, 2, 5, 6,
	7, 4, 1, 0
};
int
main(int argc, char **argv)
{
	glutInit(&argc, argv);

	glutInitWindowSize(400, 400);
	glutInitDisplayMode(GLUT_RGB | GLUT_STENCIL | GLUT_DOUBLE | GLUT_DEPTH);
	glutCreateWindow("Stenciled hidden surface removal");

	ax = 10.0;
	ay = -10.0;
	az = 0.0;

	glutDisplayFunc(drawScene);
	glutReshapeFunc(resize);
	glutCreateMenu(menu);
	glutAddMenuEntry("Motion", 3);
	glutAddMenuEntry("Stencil on", 1);
	glutAddMenuEntry("Stencil off", 2);
	glutAttachMenu(GLUT_RIGHT_BUTTON);
	glutKeyboardFunc(keyboard);
	glutMainLoop();
	return 0;             /* ANSI C requires main to return int. */
}

void
drawWireframe(int face)
{
	int i;
	glBegin(GL_LINE_LOOP);
	for (i = 0; i < 4; i++)
		glVertex3fv((GLfloat *) cube[faceIndex[face][i]]);
	glEnd();
}

void
drawFilled(int face)
{
	int i;
	glBegin(GL_POLYGON);
	for (i = 0; i < 4; i++)
		glVertex3fv((GLfloat *) cube[faceIndex[face][i]]);
	glEnd();
}

void
drawScene(void)
{

	int i;
	glEnable(GL_DEPTH_TEST);
	glDepthFunc(GL_LEQUAL);

	glClearColor(0.0, 0.0, 0.0, 0.0);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	glPushMatrix();

	glRotatef(ax, 1.0, 0.0, 0.0);
	glRotatef(-ay, 0.0, 1.0, 0.0);

	/* all the good stuff follows */

	if (stencilOn) {
		glEnable(GL_STENCIL_TEST);
		glClear(GL_STENCIL_BUFFER_BIT);
		glStencilMask(1);
		glStencilFunc(GL_ALWAYS, 0, 1);
		glStencilOp(GL_INVERT, GL_INVERT, GL_INVERT);
	}
	glColor3f(1.0, 1.0, 0.0);
	for (i = 0; i < 6; i++) {
		drawWireframe(i);
		if (stencilOn) {
			glStencilFunc(GL_EQUAL, 0, 1);
			glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
		}
		glColor3f(0.0, 0.0, 0.0);
		drawFilled(i);

		glColor3f(1.0, 1.0, 0.0);
		if (stencilOn) {
			glStencilFunc(GL_ALWAYS, 0, 1);
			glStencilOp(GL_INVERT, GL_INVERT, GL_INVERT);
		}
		glColor3f(1.0, 1.0, 0.0);
		drawWireframe(i);
	}
	glPopMatrix();

	if (stencilOn)
		glDisable(GL_STENCIL_TEST);

	/* end of good stuff */

	glutSwapBuffers();
}

void
setMatrix(void)
{
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glOrtho(-2.0, 2.0, -2.0, 2.0, -2.0, 2.0);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
}

int count = 0;

void
animation(void)
{
	/* animate the cone */

	ax += 5.0;
	ay -= 2.0;
	az += 5.0;
	if (ax >= 360)
		ax = 0.0;
	if (ay <= -360)
		ay = 0.0;
	if (az >= 360)
		az = 0.0;
	glutPostRedisplay();
	count++;
	if (count >= 60)
		glutIdleFunc(NULL);
}

void
menu(int choice)
{
	switch (choice) {
	case 3:
		count = 0;
		glutIdleFunc(animation);
		break;
	case 2:
		stencilOn = 0;
		glutSetWindowTitle("Stencil Disabled");
		glutPostRedisplay();
		break;
	case 1:
		stencilOn = 1;
		glutSetWindowTitle("Stencil Enabled");
		glutPostRedisplay();
		break;
	}
}

/* ARGSUSED1 */
void
keyboard(unsigned char c, int x, int y)
{
	switch (c) {
	case 27:
		exit(0);
		break;
	default:
		break;
	}
}

void
resize(int w, int h)
{
	glViewport(0, 0, w, h);
	setMatrix();
}
